﻿

local moduleName = "Buffs"



----------------------------
--      Localization      --
----------------------------

local L = {
	[moduleName] = "Buffs",

	["Always"] = true,
	["Enable/Disable buffs which are always shown."] = true,

	["Out Of Combat"] = true,
	["Enable/Disable Out of combat buffs."] = true,

	["Add buff"] = true,
	["Add a buff to show. Must match the exact name of the debuff, including capital case."] = true,

	["Text Color"] = true,
	["Change the text color."] = true,

	["Enable/Disable showing of "] = true,

	["Show Buffs"] = true,
	["How many buffs will show"] = true,

	["Cooldown Shadow"] = true,
	["Show shadow on buff icon."] = true,
	
	["Cooldown Text"] = true,
	["Show text on buff icon."] = true,

	["Side"] = true,
	["Which side to position buff icons at."] = true,
	["Left"] = true,
	["Right"] = true,

	["Can't delete |cffff0000%s|r from the default buff list."] = true,
	["|cffff0000%s|r removed from the buff list."] = true,
	["|cffff0000%s|r is in the buff list."] = true,
	["|cffff0000%s|r added to the buff list."] = true,
}

if GetLocale() == "zhCN" then
	L[moduleName] = "Buff-增益效果"

	L["Always"] = "一直显示"
	L["Enable/Disable buffs which are always shown."] = "选择/不选择 哪些增益效果需要一直显示的"

	L["Out Of Combat"] = "非战斗时显示"
	L["Enable/Disable Out of combat buffs."] = "选择/不选择 哪些增益效果只在非战斗状态时显示"

	L["Add buff"] = "添加增益效果"
	L["Add a buff to show. Must match the exact name of the debuff, including capital case."] = "新添加一个增益效果到buff列表中.\n必须输入正确的减益效果名称, 否则不会有效果"

	L["Text Color"] = "文字颜色"
	L["Change the text color."] = "变更文字颜色"

	L["Enable/Disable showing of "] = "选择/不选择 显示"

	L["Show Buffs"] = "显示Buff数量"
	L["How many buffs will show"] = "显示Buff数量"

	L["Cooldown Shadow"] = "CD阴影"
	L["Show shadow on buff icon."] = "阴影显示CD"
	
	L["Cooldown Text"] = "CD文字"
	L["Show text on buff icon."] = "文字显示CD"

	L["Side"] = "位置"
	L["Which side to position buff icons at."] = "设置在哪一边放置增益法术效果图标。"
	L["Left"] = "左"
	L["Right"] = "右"

	L["Can't delete |cffff0000%s|r from the default buff list."] = "不能从默认增益列表中删除 |cffff0000%s|r 。"
	L["|cffff0000%s|r removed from the buff list."] = "|cffff0000%s|r 从增益列表中删除"
	L["|cffff0000%s|r is in the buff list."] = "|cffff0000%s|r 已经在增益列表中"
	L["|cffff0000%s|r added to the buff list."] = "|cffff0000%s|r 添加到增益列表中"

elseif GetLocale() == "zhTW" then
	L[moduleName] = "Buff-增益效果"

	L["Always"] = "一直顯示"
	L["Enable/Disable buffs which are always shown."] = "選擇/不選擇 哪些增益效果需要一直顯示的"

	L["Out Of Combat"] = "非戰鬥時顯示"
	L["Enable/Disable Out of combat buffs."] = "選擇/不選擇 哪些增益效果只在非戰鬥狀態時顯示"

	L["Add buff"] = "添加增益效果"
	L["Add a buff to show. Must match the exact name of the debuff, including capital case."] = "新添加一个增益效果到buff列表中.\n必须输入正确的减益效果名称, 否则不会有效果"

	L["Text Color"] = "文字顏色"
	L["Change the text color."] = "變更文字顏色"

	L["Enable/Disable showing of "] = "選擇/不選擇 顯示"

	L["Show Buffs"] = "顯示Buff數量"
	L["How many buffs will show"] = "顯示Buff數量"

	L["Cooldown Shadow"] = "CD陰影"
	L["Show shadow on buff icon."] = "陰影顯示CD"
	
	L["Cooldown Text"] = "CD文字"
	L["Show text on buff icon."] = "文字顯示CD"

	L["Side"] = "位置"
	L["Which side to position buff icons at."] = "設置在哪一邊放置增益法術效果圖示。"
	L["Left"] = "左"
	L["Right"] = "右"

	L["Can't delete |cffff0000%s|r from the default buff list."] = "不能從默認增益列表中刪除 |cffff0000%s|r 。"
	L["|cffff0000%s|r removed from the buff list."] = "|cffff0000%s|r 從增益列表中刪除"
	L["|cffff0000%s|r is in the buff list."] = "|cffff0000%s|r 已經在增益列表中"
	L["|cffff0000%s|r added to the buff list."] = "|cffff0000%s|r 添加到增益列表中"
end

----------------------------------
--      Local Declaration      --
----------------------------------
local buffs = {
	{"DRUID", true, 0774},  -- Rejuvenation
	{"DRUID", true, 8936},  -- Regrowth
	{"DRUID", true, 33763},  -- Lifebloom
	{"DRUID", true, 48438},  -- Wild Growth
	{"DRUID", false, 1126},  -- Mark of the Wild
	{"DRUID", false, 21849},  -- Gift of the Wild
	{"DRUID", false, 0467},  -- Thorns
	{"DRUID", true, 29166},  -- Innervate
	{"DRUID", false, 33891},  -- Tree of Life
	{"DRUID", true, 22845},  -- Frenzied Regeneration
	{"DRUID", true, 2893},  -- Abolish Poison
	{"DRUID", false, 22812},  -- Barkskin
	{"DRUID", true, 50334},  -- Berserk

	{"PRIEST", false, 1243},  -- Power Word: Fortitude
	{"PRIEST", false, 21562},  -- Prayer of Fortitude
	{"PRIEST", true, 0017},  -- Power Word: Shield
	{"PRIEST", true, 0139},  -- Renew
	{"PRIEST", false, 0976},  -- Shadow Protection
	{"PRIEST", false, 27683},  -- Prayer of Shadow Protection
	{"PRIEST", false, 14752},  -- Divine Spirit
	{"PRIEST", false, 27681},  -- Prayer of Spirit
	{"PRIEST", true, 6346},  -- Fear Ward
	{"PRIEST", true, 33076},  -- Prayer of Mending
	{"PRIEST", true, 0552},  -- Abolish Disease
	{"PRIEST", true, 47585},  -- Dispersion
	{"PRIEST", true, 47788},  -- Guardian Spirit
	{"PRIEST", false, 7001},  -- Lightwell Renew

	{"PALADIN", true, 1044},  -- Hand of Freedom
	{"PALADIN", false, 20217},  -- Blessing of Kings
	{"PALADIN", false, 19740},  -- Blessing of Might
	{"PALADIN", true, 1022},  -- Hand of Protection
	{"PALADIN", false, 6940},  -- Hand of Sacrifice
	{"PALADIN", false, 1038},  -- Hand of Salvation
	{"PALADIN", false, 20911},  -- Blessing of Sanctuary
	{"PALADIN", false, 19742},  -- Blessing of Wisdom
	{"PALADIN", false, 25898},  -- Greater Blessing of Kings
	{"PALADIN", false, 25782},  -- Greater Blessing of Might
	{"PALADIN", false, 25899},  -- Greater Blessing of Sanctuary
	{"PALADIN", false, 25894},  -- Greater Blessing of Wisdom
	{"PALADIN", true, 0633},  -- Lay on Hands
	{"PALADIN", true, 53563},  -- Beacon of Light
	{"PALADIN", true, 0642},  -- Divine Shield
	{"PALADIN", true, 19752},  -- Divine Intervention
	{"PALADIN", true, 54957},  -- Glyph of Flash of Light

	{"MAGE", false, 1459},  -- Arcane Intellect
	{"MAGE", false, 23028},  -- Arcane Brilliance
	{"MAGE", true, 45438},  -- Ice Block
	{"MAGE", true, 11426},  -- Ice Barrier
	{"MAGE", true, 1463},  -- Mana Shield

	{"WARLOCK", false, 20707},  -- Soulstone Resurrection
	{"WARLOCK", false, 6307},  -- Blood Pact

	{"WARRIOR", true, 0871},  -- Shield Wall
	{"WARRIOR", true, 12975},  -- Last Stand

	{"HUNTER", true, 34477},  -- Misdirection
	{"HUNTER", true, 5384},  -- Feign Death

	{"SHAMAN", true, 0974},  -- Earth Shield
	{"SHAMAN", false, 32182},  -- Heroism
	{"SHAMAN", false, 61295},  -- Riptide

	{"ROGUE", true, 5277},  -- Evasion

	{"DEATHKNIGHT", true, 28880},  -- Gift of the Naaru
}
local buffsName = {}
local buffscName = {}
local positions ={
	["LEFT"] = L["Left"],
	["RIGHT"] = L["Right"]
}
local iconsize = 19

local incombat = false

-- localize these functions to speed up our main loop
local UnitBuff = UnitBuff
local UnitAffectingCombat = UnitAffectingCombat

----------------------------------
--      Module Declaration      --
----------------------------------

local plugin = BunchOfBars:NewModule(moduleName, "AceTimer-3.0")

plugin.revision = tonumber(("$Revision: 40 $"):match("%d+"))

plugin.options = {
	name = L[moduleName],
	args = {
		always = {
			type = "multiselect",
			name = L["Always"],
			desc = L["Enable/Disable buffs which are always shown."],
			values = {},
			get = "GetSetAlways",
			set = "GetSetAlways",
			order = 2
		},
		ooc = {
			type = "multiselect",
			name = L["Out Of Combat"],
			desc = L["Enable/Disable Out of combat buffs."],
			values = {},
			get = "GetSetOoc",
			set = "GetSetOoc",
			order = 3
		},
		add = {
			type  = "input",
			name  = L["Add buff"],
			desc  = L["Add a buff to show. Must match the exact name of the debuff, including capital case."],
			get   = "NewBuff",
			set   = "NewBuff",
			order = 4
		},
		color = {
			type = "color",
			name = L["Text Color"],
			desc = L["Change the text color."],
			get = "GetSetColor",
			set = "GetSetColor"
		},
		sbuffs = {
			type = "range",
			name = L["Show Buffs"],
			desc = L["How many buffs will show"],
			min = 1,
            		max = 8,
            		step = 1,
           		get = "GetSetBuffs",
            		set = "GetSetBuffs",
		},
		cdshadow = {
			type  = "toggle",
			name  = L["Cooldown Shadow"],
			desc  = L["Show shadow on buff icon."],
			get = "GetSetCDS",
			set = "GetSetCDS",
		},
--[[		cdtext = {
			type  = "toggle",
			name  = L["Cooldown Text"],
			desc  = L["Show text on buff icon."],
			get = "GetSetCDT",
			set = "GetSetCDT",
		},
--]]
		side = {
			type  = "select",
			name  = L["Side"],
			desc  = L["Which side to position buff icons at."],
			values = positions,
			get = "GetSetSide",
			set = "GetSetSide",
		},
	}
}

plugin.defaultDB = {
--	position = 1,
	profile = {
		cdshadow = false,
		cdtext = false,
		sbuffs = 4,
		always = {},
		ooc    = {},
		add    = {},
		color  = {
			r = 1,
			g = 0,
			b = 0
		},
		side = "RIGHT"
	}
}
for i,a in pairs(buffs) do
	buffs[i][3] = GetSpellInfo(a[3])
end

do -- let's not pollute our name space
	local _,class = UnitClass("player")

	for i,a in ipairs(buffs) do

		if a[2] then
			plugin.defaultDB.profile.always[a[3]] = true
			plugin.defaultDB.profile.ooc[a[3]]    = false
		elseif a[1] == class then
		    plugin.defaultDB.profile.always[a[3]] = false
			plugin.defaultDB.profile.ooc[a[3]]    = true
		else
			plugin.defaultDB.profile.always[a[3]] = false
			plugin.defaultDB.profile.ooc[a[3]]    = false
		end
	end
end



----------------------------------
--      Module Functions        --
----------------------------------

function plugin:OnEnable()
	self:ScheduleRepeatingTimer(self.Update, 0.5, self) -- can't use UNIT_AURA cause we need to update timers
	self:List()
end
function plugin:List()
	buffscName = {}
	buffsName = {}
	for i,a in pairs(buffs) do
		local cname = "|cff"..string.format("%02x%02x%02x", RAID_CLASS_COLORS[a[1]].r * 255, RAID_CLASS_COLORS[a[1]].g * 255, RAID_CLASS_COLORS[a[1]].b * 255)..a[3].."|r"
		buffscName[i] = cname
		buffsName[i] = a[3]
	end

	for i,a in pairs(self.db.profile.add) do
		local cname = "|cffff1476"..i.."|r"
		table.insert(buffscName, cname)
		table.insert(buffsName, i)
	end
	self.options.args.always.values = buffscName
	self.options.args.ooc.values = buffscName
end
function plugin:OnCreate(frame)
	local buffbar = CreateFrame("Frame", nil, frame)
	buffbar:SetWidth(1)
	buffbar:SetHeight(30)

	return buffbar
end


function plugin:CreateBuff(buffbar, n)
	local buff_frame = CreateFrame("Button", nil, buffbar)
	buff_frame:SetHeight(iconsize)
	buff_frame:SetWidth(iconsize - 1)
	buff_frame:ClearAllPoints()
	if self.db.profile.side == "RIGHT" then
		buff_frame:SetPoint("BOTTOMLEFT", buffbar, "BOTTOMLEFT", (n - 1) * (iconsize + 4), 2) --right side
	elseif self.db.profile.side == "LEFT" then
		buff_frame:SetPoint("BOTTOMRIGHT", buffbar, "BOTTOMRIGHT", -((n - 1) * (iconsize + 4)), 2) --left side
	end
	buff_frame:Hide()

	local t = buff_frame:CreateTexture(nil, "ARTWORK")
	t:SetVertexColor(1, 1, 1, 1)
	t:SetTexCoord(0.2, 0.8, 0.1, 0.9)
	t:SetAllPoints(buff_frame)
	t:Show()
	buff_frame.t = t

	local cd = CreateFrame("Cooldown", nil, buff_frame, "CooldownFrameTemplate")
	cd:SetReverse(true)
	cd:SetAllPoints(buff_frame)
	cd:Hide()
	buff_frame.cd = cd

	local font = buff_frame:CreateFontString(nil, "OVERLAY")
	font:SetFont("Interface\\Addons\\BunchOfBars\\Textures\\b.ttf", 20)
	font:SetTextColor(self.db.profile.color.r, self.db.profile.color.g, self.db.profile.color.b, 1)
	font:SetShadowColor(0, 0, 0, 1)
	font:SetShadowOffset(1, -1)
	font:ClearAllPoints()
	font:SetPoint("TOPLEFT", buff_frame, "TOPLEFT", -2, 4)
	font:Show()
	buff_frame.tfont = font

	font = buff_frame:CreateFontString(nil, "OVERLAY")
	font:SetFont("Interface\\Addons\\BunchOfBars\\Textures\\b.ttf", 18)
	font:SetTextColor(self.db.profile.color.r, self.db.profile.color.g, self.db.profile.color.b, 1)
	font:SetShadowColor(0, 0, 0, 1)
	font:SetShadowOffset(1, -1)
	font:ClearAllPoints()
	font:SetPoint("BOTTOMRIGHT", buff_frame, "BOTTOMRIGHT", 1, -1)
	font:Show()
	buff_frame.afont = font


	local border = buff_frame:CreateTexture(nil, "BORDER") --ARTWORK
	border:SetTexture("Interface\\Addons\\BunchOfBars\\Textures\\border")
	border:SetAlpha(1)
	border:SetVertexColor(0, 1, 1, 1)
	border:ClearAllPoints()
	border:SetPoint("CENTER", buff_frame, "CENTER", 0, 0)
	border:SetWidth(iconsize + 3)
	border:SetHeight(iconsize + 3)
	border:Show()
	buff_frame.border = border

	buffbar[n] = buff_frame

end


function plugin:OnUpdate(frame)
	local buffbar = frame.parts[moduleName]
	local n = 1

	for i = 1,64 do
		local name, _, texture, applications, _, duration, timeleft, mine = UnitBuff(frame.unit, i)
		if not name or (n > self.db.profile.sbuffs) then break end

		if self.db.profile.always[name] or (not incombat and self.db.profile.ooc[name]) then
			if not buffbar[n] then
				self:CreateBuff(buffbar, n)
			end
			if mine then
				buffbar[n].border:SetVertexColor(0, 1, 1, 1)
			else
				buffbar[n].border:SetVertexColor(1, 0.85, 0, 1)
			end
			
			buffbar[n].t:SetTexture(texture)

			if self.db.profile.cdshadow and duration and duration > 0 then
				local startcd = GetTime() + timeleft - duration
				buffbar[n].cd:SetCooldown(timeleft - duration, duration)
				buffbar[n].cd:Show()
			else
				buffbar[n].cd:Hide()
			end
--[[
			if self.db.profile.cdtext and timeleft and timeleft > 0 then
				timeleft = timeleft - GetTime()
				if timeleft > 60 then timeleft = timeleft / 60 end
				timeleft = math.floor(timeleft)

				if mine then
					buffbar[n].tfont:SetAlpha(1)
				else
					buffbar[n].tfont:SetAlpha(0.4)
				end

				buffbar[n].tfont:SetText(timeleft)
			else
				buffbar[n].tfont:SetText()
			end
--]]
			if applications > 1 then
				if mine then
					buffbar[n].afont:SetAlpha(1)
				else
					buffbar[n].afont:SetAlpha(0.4)
				end
				buffbar[n].afont:SetText(applications)
			else
				buffbar[n].afont:SetText()
			end

			buffbar[n]:Show()

			n = n + 1
		end
	end
	buffbar:SetWidth((n - 1) * (iconsize + 4) + 1)
	while buffbar[n] do
		buffbar[n]:Hide()
		buffbar[n].t:SetTexture()
		buffbar[n].tfont:SetText()
		buffbar[n].afont:SetText()
		n = n + 1
	end

end


function plugin:Update()
	incombat = UnitAffectingCombat("player") or UnitAffectingCombat("target")

	self:UpdateAll()
end


----------------------------------
--      Option Handlers         --
----------------------------------

function plugin:GetSetColor(_, r, g, b)
	if type(r) == "nil" then return self.db.profile.color.r, self.db.profile.color.g, self.db.profile.color.b end

	self.db.profile.color.r = r
	self.db.profile.color.g = g
	self.db.profile.color.b = b

	for _,frame in pairs(self.core.frames) do
		local buffbar, n = frame.parts[moduleName], 1

		while buffbar[n] do
			buffbar[n].afont:SetTextColor(self.db.profile.color.r ,self.db.profile.color.g, self.db.profile.color.b, 1)
			buffbar[n].tfont:SetTextColor(self.db.profile.color.r ,self.db.profile.color.g, self.db.profile.color.b, 1)
			n = n + 1
		end
	end
end

function plugin:GetSetBuffs(_, v)
	if type(v) == "nil" then return self.db.profile.sbuffs end

	if self.db.profile.sbuffs ~= v then
		self.db.profile.sbuffs = v
		
		self:Update()
	end
end

function plugin:GetSetCDS(_, v)
	if type(v) == "nil" then return self.db.profile.cdshadow end

	if self.db.profile.cdshadow ~= v then
		self.db.profile.cdshadow = v

		self:UpdateAll()
	end
end

function plugin:GetSetCDT(_, v)
	if type(v) == "nil" then return self.db.profile.cdtext end

	if self.db.profile.cdtext ~= v then
		self.db.profile.cdtext = v

		self:UpdateAll()
	end
end
function plugin:GetSetAlways(_, n, v)
	if type(v) == "nil" then return self.db.profile.always[buffsName[n]] end

	if IsShiftKeyDown() then
		self:DeleteBuff(n)
	else
		self.db.profile.always[buffsName[n]] = v
	end
end
function plugin:GetSetOoc(_, n, v)
	if type(v) == "nil" then return self.db.profile.ooc[buffsName[n]] end

	if IsShiftKeyDown() then
		self:DeleteBuff(n)
	else
		self.db.profile.ooc[buffsName[n]] = v
	end
end
function plugin:NewBuff(_, n)
	if type(n) == "nil" then return "" end
	local add = true
	n = strtrim(n)
	for i,k in pairs(buffsName) do
		if k == n then
			add = false
			break
		end
	end
	if add then
		self.db.profile.add[n] = true
		self.core:Print(string.format(L["|cffff0000%s|r added to the buff list."], n))
		self.db.profile.always[n] = false
		self.db.profile.ooc[n] = false
		table.insert(buffscName, "|cffff1476"..n.."|r")
		table.insert(buffsName, n)
	else
		self.core:Print(string.format(L["|cffff0000%s|r is in the buff list."], n))
	end

end
function plugin:DeleteBuff(n)
	if buffs[n] then
		self.core:Print(string.format(L["Can't delete |cffff0000%s|r from the default buff list."], buffs[n][3]))
		return
	end
	self.db.profile.add[buffsName[n]] = nil
	self.db.profile.ooc[buffsName[n]] = nil
	self.db.profile.always[buffsName[n]] = nil
	self.core:Print(string.format(L["|cffff0000%s|r removed from the buff list."], buffsName[n]))
	buffsName[n] = nil
	buffscName[n] = nil
end
function plugin:GetSetSide(_, v)
	if type(v) == "nil" then return self.db.profile.side end

	if self.db.profile.side ~= v then
		self.db.profile.side = v

		self.core:UpdateSideOrder()

		self:UpdateAllWith(function(frame)
			local buffbar = frame.parts[moduleName]
			local n = 1
			while buffbar[n] do
				buffbar[n]:Hide()
				buffbar[n].t:SetTexture()
				buffbar[n]:SetScript("OnEnter", nil)
				buffbar[n]:SetScript("OnLeave", nil)
				buffbar[n].tfont:SetText()
				buffbar[n].afont:SetText()
				buffbar[n] = nil
				n = n + 1
			end

			self.core:UpdateSide(frame)
		end)
		self:UpdateAll()
	end
end
